﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace LiteFramework
{
    public class NetHelper
    {
        private NetHelper()
        {
        }

        #region HttpRequest

        /// <summary>
        /// 发送http请求
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="method">请求方式。get/post</param>
        /// <param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <returns></returns>
        [Obsolete("建议使用 HttpPost/HttpGet 方法")]
        public static string HttpRequest(Uri uri, string method, string data)
        {
            return HttpRequest(uri, method, data, Encoding.Default, null);
        }

        /// <summary>
        /// 发送http请求
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="method">请求方式。get/post</param>
        /// <<param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">编码</param>
        /// <returns></returns>
        [Obsolete("建议使用 HttpPost/HttpGet 方法")]
        public static string HttpRequest(Uri uri, string method, string data, Encoding encoding)
        {
            return HttpRequest(uri, method, data, encoding, null);
        }

        /// <summary>
        /// 发送http请求
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="method">请求方式。get/post</param>
        /// <<param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">编码</param>
        /// <param name="head">报文头</param>
        /// <returns></returns>
        [Obsolete("建议使用 HttpPost/HttpGet 方法")]
        public static string HttpRequest(Uri uri, string method, string data, Encoding encoding, IDictionary<HttpRequestHeader, string> head)
        {
            return HttpRequest(uri, method, data, encoding, head, -1);
        }

        /// <summary>
        /// 发送http请求
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="method">请求方式。get/post</param>
        /// <<param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">编码</param>
        /// <param name="head">报文头</param>
        /// <param name="timeout">超时时间</param>
        /// <returns></returns>
        [Obsolete("建议使用 HttpPost/HttpGet 方法")]
        public static string HttpRequest(Uri uri, string method, string data, Encoding encoding, IDictionary<HttpRequestHeader, string> head, int timeout)
        {
            return HttpRequest(uri, method, data, encoding, head, timeout, null);
        }

        /// <summary>
        /// 发送http请求
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="method">请求方式。get/post</param>
        /// <<param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">编码</param>
        /// <param name="head">报文头</param>
        /// <param name="timeout">超时时间</param>
        /// <param name="proxy">用户代理</param>
        /// <returns></returns>
        [Obsolete("建议使用 HttpPost/HttpGet 方法")]
        public static string HttpRequest(Uri uri, string method, string data, Encoding encoding, IDictionary<HttpRequestHeader, string> head, int timeout, IWebProxy proxy)
        {
            if (uri.Scheme != Uri.UriSchemeHttp)
                throw new NotSupportedException();

            if (String.IsNullOrEmpty(method))
                method = "GET";
            else
                method = method.ToUpper();

            if (head == null)
                head = new Dictionary<HttpRequestHeader, string>();

            if (!head.ContainsKey(HttpRequestHeader.Connection))
                head.Add(HttpRequestHeader.Connection, "close");

            if (!head.ContainsKey(HttpRequestHeader.CacheControl))
                head.Add(HttpRequestHeader.CacheControl, "no-cache");

            if (!head.ContainsKey(HttpRequestHeader.Accept))
                head.Add(HttpRequestHeader.Accept, "*/*");

            if (!head.ContainsKey(HttpRequestHeader.AcceptLanguage))
                head.Add(HttpRequestHeader.AcceptLanguage, "zh-CN");

            if (!head.ContainsKey(HttpRequestHeader.UserAgent))
                head.Add(HttpRequestHeader.UserAgent, "Mozilla/4.0 (compatible;)");

            if (data != null)
                head[HttpRequestHeader.ContentLength] = encoding.GetByteCount(data).ToString();
            else
                head.Remove(HttpRequestHeader.ContentLength);

            DateTimeFormatInfo fi = new CultureInfo("en-US", false).DateTimeFormat;
            head[HttpRequestHeader.Date] = DateTime.Now.ToUniversalTime().ToString("R", fi);

            StringBuilder request = new StringBuilder();
            request.AppendFormat("{0} {1} HTTP/1.1\r\n", method, uri.PathAndQuery);
            request.AppendFormat("Host: {0}\r\n", uri.Authority);

            foreach (HttpRequestHeader key in head.Keys)
            {
                string value = head[key];

                if (!String.IsNullOrEmpty(value))
                    request.AppendFormat("{0}: {1}\r\n", TextHelper.Amead(key.ToString(), '-'), value);
            }

            request.Append("\r\n");
            if (data != null)
                request.Append(data);

            string response;
            using (TcpClient client = CreateTcpClient(uri, proxy, timeout))
            {
                response = Request(client, uri.Host, uri.Port, request.ToString(), encoding);
            }

            if (!String.IsNullOrEmpty(response))
            {
                int pos = response.IndexOf("\r\n\r\n");
                if (pos > 0)
                {
                    pos += 4;
                    if (pos <= response.Length)
                    {
                        string heads = response.Substring(0, pos - 4);
                        if (IsHeads(heads))
                            return response.Substring(pos);
                    }
                }
                else if (IsHeads(response))
                {
                    return String.Empty;
                }

                return response;
            }
            else
            {
                throw new WebException("已经成功连接远程服务器，但是服务器没有应答。", WebExceptionStatus.ReceiveFailure);
            }
        }

        #region 2015-09-09.New

        private static readonly string defaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
        public delegate void CaptureHandler(string str);
        public event CaptureHandler ResponseCompleted;
        public event CaptureHandler BeforeRequest;

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;//总是接受
        }

        /// <summary>
        /// 发送 Post 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="parameters">请求的数据</param>
        /// <param name="timeoutSecond">超时时间（秒）。</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string HttpPost(string uri, IDictionary<string, string> parameters, int? timeoutSecond, Encoding encoding)
        {
            string postData = null;

            //如果需要POST数据  
            if (!(parameters == null || parameters.Count == 0))
            {
                StringBuilder sb = new StringBuilder();
                int i = 0;
                foreach (string key in parameters.Keys)
                {
                    if (i == 0)
                    {
                        sb.AppendFormat("{0}={1}", key, parameters[key]);
                    }
                    else
                    {
                        sb.AppendFormat("&{0}={1}", key, parameters[key]);
                    }
                    i++;
                }
                postData = sb.ToString();
            }

            return HttpPost(uri, postData, timeoutSecond, encoding, null, null);
        }
        /// <summary>
        /// 发送 Post 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="postData">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <returns></returns>
        public static string HttpPost(string uri, string postData)
        {
            return HttpPost(uri, postData, null, null, null, null);
        }
        /// <summary>
        /// 发送 Post 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="postData">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="timeoutSecond">超时时间(秒)</param>
        /// <returns></returns>
        public static string HttpPost(string uri, string postData, int timeoutSecond)
        {
            return HttpPost(uri, postData, timeoutSecond, null, null, null);
        }
        /// <summary>
        /// 发送 Post 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="postData">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string HttpPost(string uri, string postData, Encoding encoding)
        {
            return HttpPost(uri, postData, null, encoding, null, null);
        }
        /// <summary>
        /// 发送 Post 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="postData">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="timeoutSecond">超时时间(秒)</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string HttpPost(string uri, string postData, int? timeoutSecond, Encoding encoding)
        {
            return HttpPost(uri, postData, timeoutSecond, encoding, null, null);
        }
        /// <summary>
        /// 发送 Post 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="postData">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="timeoutSecond">超时时间(秒)</param>
        /// <param name="encoding">字符编码</param>
        /// <param name="userAgent">用户代理</param>
        /// <param name="cookies"></param>
        /// <returns></returns>
        public static string HttpPost(string uri, string postData, int? timeoutSecond, Encoding encoding, string userAgent, CookieCollection cookies)
        {
            if (string.IsNullOrEmpty(uri))
                throw new ArgumentNullException("uri");

            if (uri.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
                uri = "http://" + uri;

            if (encoding == null)
                encoding = Encoding.UTF8;

            HttpWebRequest request;//处理证书问题
            if (uri.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(uri) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;
            }
            else
            {
                request = WebRequest.Create(uri) as HttpWebRequest;
            }

            if (request == null)
                throw new Exception("创建连接失败。uri=" + uri);

            request.Method = "POST";
            //request.Headers.Add("X_FORWARDED_FOR", "0.0.0.0"); // 伪装Ip

            request.UserAgent = !string.IsNullOrEmpty(userAgent) ? userAgent : defaultUserAgent; // 用户代理

            if (timeoutSecond.HasValue) // 超时
                request.Timeout = timeoutSecond.Value;

            if (cookies != null) // cookies
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }
            request.KeepAlive = true;
            request.Referer = null;
            request.Headers["Accept-Language"] = "zh-cn";
            request.ServicePoint.Expect100Continue = false;
            request.Headers["Accept-Encoding"] = "gzip, deflate";
            //request.Accept = "image*";
            if (postData != null)
            {
                //设置编码，搞不好出来的就是???
                byte[] postDataBuffer = encoding.GetBytes(postData); //Encoding.UTF8.GetBytes(postData);
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = postDataBuffer.Length;
                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(postDataBuffer, 0, postDataBuffer.Length);
                }
            }

            using (HttpWebResponse resp = request.GetResponse() as HttpWebResponse)
            {
                using (Stream stream = resp.GetResponseStream())
                {
                    if (resp.Headers["Content-Encoding"] == "gzip")
                    {
                        using (StreamReader reader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress), encoding))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                    else
                    {
                        using (StreamReader reader = new StreamReader(stream, encoding))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 发送 Get 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="parameters">请求的数据</param>
        /// <param name="timeoutSecond">超时时间（秒）。</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string HttpGet(string uri, IDictionary<string, string> parameters, int? timeoutSecond, Encoding encoding)
        {
            string data = null;
            if (!(parameters == null || parameters.Count == 0))
            {
                StringBuilder sb = new StringBuilder();
                int i = 0;
                foreach (string key in parameters.Keys)
                {
                    if (i == 0)
                    {
                        sb.AppendFormat("{0}={1}", key, parameters[key]);
                    }
                    else
                    {
                        sb.AppendFormat("&{0}={1}", key, parameters[key]);
                    }
                    i++;
                }
                data = sb.ToString();
            }

            return HttpGet(uri, data, timeoutSecond, encoding, null, null);
        }
        /// <summary>
        /// 发送 Get 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <returns></returns>
        public static string HttpGet(string uri)
        {
            return HttpGet(uri, null, null, null, null, null);
        }
        /// <summary>
        /// 发送 Get 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <returns></returns>
        public static string HttpGet(string uri, string data)
        {
            return HttpGet(uri, data, null, null, null, null);
        }
        /// <summary>
        /// 发送 Get 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="timeoutSecond">超时时间（秒）。</param>
        /// <returns></returns>
        public static string HttpGet(string uri, string data, int timeoutSecond)
        {
            return HttpGet(uri, data, timeoutSecond, null, null, null);
        }
        /// <summary>
        /// 发送 Get 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string HttpGet(string uri, string data, Encoding encoding)
        {
            return HttpGet(uri, data, null, encoding, null, null);
        }
        /// <summary>
        /// 发送 Get 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="timeoutSecond">超时时间（秒）。</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string HttpGet(string uri, string data, int timeoutSecond, Encoding encoding)
        {
            return HttpGet(uri, data, timeoutSecond, encoding, null, null);
        }
        /// <summary>
        /// 发送 Get 请求，并返回远程服务器的响应结果
        /// </summary>
        /// <param name="uri">请求uri</param>
        /// <param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="timeoutSecond">超时时间（秒）。</param>
        /// <param name="encoding">字符编码</param>
        /// <param name="userAgent">用户代理</param>
        /// <param name="cookies"></param>
        /// <returns></returns>
        public static string HttpGet(string uri, string data, int? timeoutSecond, Encoding encoding, string userAgent, CookieCollection cookies)
        {
            if (string.IsNullOrEmpty(uri))
                throw new ArgumentNullException("uri");

            if (uri.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
                uri = "http://" + uri;

            if (encoding == null)
                encoding = Encoding.UTF8;

            if (data != null)
            {
                uri += (uri.IndexOf("?") != -1) ? "&" : "?";
                uri += data;
            }

            HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
            if (request == null)
                throw new Exception("创建连接失败。uri=" + uri);

            request.Method = "GET";
            //request.Headers.Add("X_FORWARDED_FOR", "0.0.0.0"); // 伪装Ip

            request.UserAgent = !string.IsNullOrEmpty(userAgent) ? userAgent : defaultUserAgent; // 用户代理

            if (timeoutSecond.HasValue) // 超时
                request.Timeout = timeoutSecond.Value * 1000;

            if (cookies != null) // cookies
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }

            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                using (Stream stream = response.GetResponseStream())
                {
                    if (response.Headers["Content-Encoding"] == "gzip")
                    {
                        using (StreamReader reader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress), encoding))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                    else
                    {
                        using (StreamReader reader = new StreamReader(stream, encoding))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                }
            }
        }



        /// <summary>
        /// 方法来自浦发行测试包
        ///     By HYD
        ///     2015-12-18
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="strPostdata"></param>
        /// <param name="strEncoding"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        private string OpenReadWithHttps(string URL, string strPostdata, Encoding encoding, string flag, int timeout)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            request.Method = "post";
            request.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*";
            request.Headers.Add("Accept-Language", "zh-cn");
            //            request.Headers.Add("Content-Type", "text/plain");
            //            request.Headers.Add("Proxy-Connection", "Keep-Alive");
            //            request.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
            request.Headers.Add("Pragma", "no-cache");
            //           request.Credentials = CredentialCache.DefaultNetworkCredentials;
            //           request.Headers.Add("User-Agent", "Microsoft Internet Explorer");
            //           request.Headers.Add(("Host", "www.uuu9.com");
            if (flag == "1")
                request.ContentType = "INFOSEC_SIGN/1.0d";
            else
                request.ContentType = "INFOSEC_VERIFY_SIGN/1.0";

            request.Timeout = timeout;

            byte[] buffer = encoding.GetBytes(strPostdata);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
            {
                return reader.ReadToEnd();
            }
        }

        #endregion

        #endregion

        #region TcpRequest

        /// <summary>
        /// 发送Tcp请求
        /// </summary>
        /// <param name="hostName">服务器</param>
        /// <param name="port">端口</param>
        /// <<param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string TcpRequest(string hostName, int port, string data, Encoding encoding)
        {
            return TcpRequest(hostName, port, data, encoding, -1);
        }

        /// <summary>
        /// 发送Tcp请求
        /// </summary>
        /// <param name="hostName">服务器</param>
        /// <param name="port">端口</param>
        /// <<param name="data">请求的数据。格式：id=100&amp;name=john&amp;.....</param>
        /// <param name="encoding">字符编码</param>
        /// <param name="timeout">超时时间</param>
        /// <returns></returns>
        public static string TcpRequest(string hostName, int port, string data, Encoding encoding, int timeout)
        {
            using (TcpClient client = CreateTcpClient(null, null, timeout))
            {
                return Request(client, hostName, port, data, encoding);
            }
        }

        #endregion

        #region FtpDownload

        public static void FtpDownload(Uri uri, string localFile)
        {
            FtpDownload(uri, localFile, null, null);
        }

        public static void FtpDownload(Uri uri, string localFile, string user, string password)
        {
            if (uri.Scheme != Uri.UriSchemeFtp)
                throw new NotSupportedException();

            if (String.IsNullOrEmpty(localFile))
                throw new ArgumentException("localFile");

            FileInfo fi = new FileInfo(localFile);

            // ...
            FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.DownloadFile;
            request.UseBinary = true;
            //request.Timeout = setting.Timeout * 1000;

            if (!String.IsNullOrEmpty(user))
                request.Credentials = new NetworkCredential(user, password);

            // ...
            using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
            {
                using (Stream rs = response.GetResponseStream())
                {
                    long cl = response.ContentLength;
                    int bufferSize = 2048;
                    int readCount;

                    using (FileStream fs = new FileStream(fi.FullName, FileMode.Create))
                    {
                        byte[] buffer = new byte[bufferSize];
                        readCount = rs.Read(buffer, 0, bufferSize);

                        while (readCount > 0)
                        {
                            fs.Write(buffer, 0, readCount);
                            readCount = rs.Read(buffer, 0, bufferSize);
                        }

                        fs.Close();
                    }

                    rs.Close();
                }

                response.Close();
            }
        }

        #endregion

        #region Connect test

        public static bool TestConnect(Uri uri)
        {
            return TestConnect(uri.Host, uri.Port);
        }

        public static bool TestConnect(string hostName, int port)
        {
            bool connected;

            using (TcpClient client = CreateTcpClient(null, null, 1500))
            {
                try
                {
                    client.Connect(hostName, port);
                    connected = client.Connected;
                }
                catch
                {
                    connected = false;
                }
                finally
                {
                    client.Close();
                }
            }

            return connected;
        }

        #endregion

        #region NetworkStream Write Read

        public static void NetworkWrite(NetworkStream ns, byte[] buffer)
        {
            NetworkWrite(ns, buffer, 0, buffer.Length);
        }

        public static void NetworkWrite(NetworkStream ns, byte[] buffer, int offset, int size)
        {
            if (ns.CanWrite)
            {
                ns.Write(buffer, offset, size);
                ns.Flush();
            }
        }

        public static byte[] NetworkRead(NetworkStream ns)
        {
            return NetworkRead(ns, -1);
        }

        public static byte[] NetworkRead(NetworkStream ns, int size)
        {
            return ReadStream(ns, size, 1024);
        }

        private static byte[] ReadStream(NetworkStream ns, int size, int bufferSize)
        {
            if (size == 0)
                return new byte[] { };

            if (size != -1 && size < bufferSize)
                bufferSize = size;

            List<byte> data = new List<byte>(bufferSize);

            if (ns.CanRead)
            {
                int numRead = 0;
                byte[] buffer = new byte[bufferSize];

                do
                {
                    numRead = ns.Read(buffer, 0, buffer.Length);

                    if (numRead == buffer.Length)
                    {
                        data.AddRange(buffer);
                    }
                    else if (numRead > 0)
                    {
                        for (int i = 0; i < numRead; i++)
                        {
                            data.Add(buffer[i]);
                            if (size != -1 && data.Count >= size)
                            {
                                break;
                            }
                        }
                    }
                }
                while (numRead != 0 & !(size != -1 && data.Count >= size));
                //while (ns.DataAvailable & !(size != -1 && data.Count >= size));   // DataAvailable 不可靠
            }

            return data.ToArray();
        }

        #endregion

        #region TCP Write Read

        public static void NetworkWrite(TcpClient client, byte[] buffer)
        {
            NetworkWrite(client, buffer, 0, buffer.Length);
        }

        public static void NetworkWrite(TcpClient client, byte[] buffer, int offset, int size)
        {
            TcpWrite(client, buffer, 0, buffer.Length, false);
        }

        public static void NetworkWriteClose(TcpClient client, byte[] buffer)
        {
            NetworkWriteClose(client, buffer, 0, buffer.Length);
        }

        public static void NetworkWriteClose(TcpClient client, byte[] buffer, int offset, int size)
        {
            TcpWrite(client, buffer, 0, buffer.Length, true);
        }

        private static void TcpWrite(TcpClient client, byte[] buffer, int offset, int size, bool end)
        {
            if (client.Connected)
            {
                NetworkStream ns = client.GetStream();
                try
                {
                    NetworkWrite(ns, buffer, offset, size);
                }
                finally
                {
                    if (end && ns != null)
                    {
                        ns.Close();
                        ns.Dispose();
                    }

                    ns = null;
                }
            }
        }

        public static byte[] NetworkRead(TcpClient client)
        {
            return NetworkRead(client, -1);
        }

        public static byte[] NetworkRead(TcpClient client, int size)
        {
            return TcpRead(client, size, false);
        }

        public static byte[] NetworkReadClose(TcpClient client)
        {
            return NetworkReadClose(client, -1);
        }

        public static byte[] NetworkReadClose(TcpClient client, int size)
        {
            return TcpRead(client, size, true);
        }

        private static byte[] TcpRead(TcpClient client, int size, bool end)
        {
            if (client.Connected)
            {
                NetworkStream ns = client.GetStream();
                try
                {
                    return ReadStream(ns, size, client.ReceiveBufferSize);
                }
                finally
                {
                    if (end && ns != null)
                    {
                        ns.Close();
                        ns.Dispose();
                    }

                    ns = null;
                }
            }
            else
            {
                return null;
            }
        }

        #endregion

        #region Private

        private static string Request(TcpClient client, string hostName, int port, string data, Encoding encoding)
        {
            byte[] send = encoding.GetBytes(data);
            byte[] recv;

            try
            {
                client.Connect(hostName, port);

                using (NetworkStream ns = client.GetStream())
                {
                    NetworkWrite(ns, send);
                    recv = ReadStream(ns, -1, client.ReceiveBufferSize);

                    ns.Close();
                }
            }
            finally
            {
                client.Close();
            }

            return ((recv != null && recv.Length != 0) ? encoding.GetString(recv) : null);
        }

        private static TcpClient CreateTcpClient(Uri target, IWebProxy proxy, int timeout)
        {
            TcpClient client;

            if (proxy != null)
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(target);
                request.Method = "CONNECT";
                request.Proxy = proxy;
                request.ServicePoint.Expect100Continue = false; // 必须在设置 WebProxy 之后

                using (WebResponse response = request.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        const BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Instance);

                        Type t = stream.GetType();
                        PropertyInfo pi = t.GetProperty("Connection", flags);
                        Object value = pi.GetValue(stream, null);

                        if (value != null)
                        {
                            t = value.GetType();
                            pi = t.GetProperty("NetworkStream", flags);
                            value = pi.GetValue(value, null);

                            if (value is NetworkStream)
                            {
                                t = value.GetType();
                                pi = t.GetProperty("Socket", flags);
                                value = pi.GetValue(value, null);

                                if (value is Socket)
                                {
                                    client = new TcpClient();
                                    client.Client = (Socket)value;
                                }
                            }
                        }

                        throw new ArgumentException("proxy");
                    }
                }
            }
            else
            {
                client = new TcpClient();
            }

            if (client != null && timeout >= 0)
            {
                client.SendTimeout = client.ReceiveTimeout = timeout;
            }

            return client;
        }

        private static bool IsHeads(string s)
        {
            if (s == null)
                return false;

            return (s.Trim().StartsWith("HTTP/1.", StringComparison.OrdinalIgnoreCase));
        }

        #endregion
    }

    public class HttpParamWriter
    {
        private Dictionary<string, string> list = null;
        public HttpParamWriter()
        {
            list = new Dictionary<string, string>();
        }
        public HttpParamWriter(string url)
            : this()
        {
            this.Url = url;
        }

        /// <summary>
        /// url。如: http://www.baidu.com
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// 添加参数值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public HttpParamWriter Add(string key, string value)
        {
            if (!string.IsNullOrEmpty(key))
            {
                if (list.ContainsKey(key))
                    list[key] = value;
                else
                    list.Add(key, value);
            }

            return this;
        }

        /// <summary>
        /// 删除参数值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public HttpParamWriter Remove(string key)
        {
            if (!string.IsNullOrEmpty(key) && list.ContainsKey(key))
                list.Remove(key);

            return this;
        }

        public override string ToString()
        {
            string param = null;
            foreach (var item in list)
            {
                if (!string.IsNullOrEmpty(param))
                    param += "&";

                param += string.Format("{0}={1}", item.Key, item.Value);
            }

            if (!string.IsNullOrEmpty(this.Url))
            {
                if (!string.IsNullOrEmpty(param))
                    return this.Url + (this.Url.IndexOf("?") != -1 ? "&" : "?") + param;
                else
                    return this.Url;
            }

            return param;
        }
    }
}
